<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>

        // 原型链继承  
        // 核心 是 子类的原型  指向父类的实例  
        // 优点:  能够继承父类所有的属性和方法 
        // 缺点  :
        //     没有自己的原型 
        //     继承下来的属性不在自己的身上在原型身上   
        function Person(name,age){
            this.name = name;
            this.age = age;

        }

        Person.prototype.sayHello = function(){
            console.log('hello world');
        }



        function Student(gender,name){
            this.gender = gender;
            this.name = name;
        }
        // 子类的原型 指向父类的实例 
        Student.prototype = new Person('jack',18);

        

        const s1 = new Student('男','Peter');
        console.log(s1);
        // console.log(s1.name);
        // console.log(s1.age);
        // console.log(s1.gender);
        // s1.sayHello();


        // 1. 创建了一个Student的对象 s1
        // 每个对象身上有个属性 __proto__ 
        // s1.__proto__ === Student.prototype

        // a ==b  b==c   => a ==c
        //2 . 在创建实例以前  
        // 把 Student的prototype赋值为 new Person('jack',18) 的对象 (Person的示例)
        // s1.__proto__ === new Person('jack',18)


        // 访问s1的name属性  
        // 根据访问原则 自己有 用自己的  自己没有 在自己的__proto__上面查找
        // 自己的__proto__ 指向的是构造函数的prototype 
        // 因为我们的 Student的prototype  是  new Person('jack',18)

        // 所以 s1的__proto__ 就是 new Person('jack',18)

        // 自己本来就有 所以直接输出  Peter 

        // 访问s1的age属性 
        // s1本身没有 于是到 __proto__ 上面找  也就是来到  new Person('jack',18)
        // 上找  它身上有  于是返回 18 

        // 访问s1的gender 属性 
        // 自己有  直接输出  


        // 访问s1的方法 sayHello

        // 自己没有 到  __proto__上找  
        // 自己的 __proto__是   new Person('jack',18) 这个实例身上也没有 
        // 到 new Person('jack',18)的构造函数Person原型上找  
        // Person的原型上有 sayHello 方法  

        // 可以正常调用  

    </script>
</body>
</html>